﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Configuration;
using System.Linq;
using System.Net.Http;
using System.Web;
using JWT;
using JWT.Algorithms;
using JWT.Serializers;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using System.Threading;

using Pay.TO;
using Pay.Core;
using Pay.DTO;
using Pay.IService;

namespace Pay.Token {
    public class AuthHelper {
        private int timspanExpiredMinutes = int.Parse(ConfigurationManager.AppSettings["token_out_times"]);
        private string token_key = ConfigurationManager.AppSettings["token_key"];
        private const int url_expire = 3;//分

        //log使用
        public string query_str { get; set; }
        public string form_str { get; set; }
        public string other_str { get; set; }
        public string timestamp { get; set; }
        public string nonce { get; set; }
        public string sign { get; set; }
        public string vSign { get; set; }
        private SecuritySignHelper _securitySignHelper { get; set; }

        public AuthHelper() {
            _securitySignHelper = new SecuritySignHelper();
        }

        public async Task<ResultMessage<bool>> ValidateSign(HttpRequestMessage requestMessage, CancellationToken cancellationToken) {
            string partner = string.Empty;
            if (requestMessage.Headers.Contains(SecuritySignHelper.Partner))
                partner = requestMessage.Headers.GetValues(SecuritySignHelper.Partner).FirstOrDefault();
            else
                return ResultToJson.Json<bool>("header中没有包含partner");

         //  if (RequestMethod.valid_sign == false)
#if DEBUG 
                return ResultToJson.Json(true);
#endif
            timestamp = string.Empty;
            if (requestMessage.Headers.Contains("timestamp")) {
                timestamp = requestMessage.Headers.GetValues("timestamp").FirstOrDefault();
                DateTime ts1;
                if (DateTime.TryParse(timestamp, out ts1)) {
#if !DEBUG
                    //var dt = ts1.AddMinutes(url_expire);
                    //bool falg = dt > DateTime.Now;
                    //if (!falg)
                    //return ResultToJson.Json<bool>("header中timestamp超时");
#endif
                } else
                    return ResultToJson.Json<bool>("header中timestamp无效");
            } else
                return ResultToJson.Json<bool>("header中没有包含timestamp");

            nonce = string.Empty;
            if (requestMessage.Headers.Contains("nonce")) {
                nonce = requestMessage.Headers.GetValues("nonce").FirstOrDefault();
                if (nonce.Length != 8)
                    return ResultToJson.Json<bool>("header中nonce无效");
            } else
                return ResultToJson.Json<bool>("header中没有包含nonce");

            //string sign = string.Empty;
            if (requestMessage.Headers.Contains(SecuritySignHelper.Sign))
                sign = requestMessage.Headers.GetValues(SecuritySignHelper.Sign).FirstOrDefault();
            else
                return ResultToJson.Json<bool>("header中没有包含sign");

            string partnerKey = "";
            if (GetPartnerKey(partner, out partnerKey) && !string.IsNullOrWhiteSpace(partnerKey)) {
                NameValueCollection postCollection = null;
                var requestUri = new Uri(requestMessage.RequestUri.ToString());
                MediaTypeHeaderValue contentType = requestMessage.Content.Headers.ContentType;
                if (contentType != null) {
                    if (contentType.MediaType == "application/x-www-form-urlencoded") {
                        //postCollection = await requestMessage..Content.ReadAsFormDataAsync();
                        postCollection = ((HttpContextBase)requestMessage.Properties["MS_HttpContext"]).Request.Form;
                    } else
                        other_str = await requestMessage.Content.ReadAsStringAsync();
                }
                NameValueCollection getCollection = HttpUtility.ParseQueryString(requestUri.Query, System.Text.Encoding.GetEncoding("utf-8"));
                //根据请求数据获取MD5签名  
                vSign = _securitySignHelper.GetSecuritySign(getCollection, partnerKey, timestamp, nonce, postCollection, other_str);
                query_str = _securitySignHelper.query_str;
                form_str = _securitySignHelper.form_str;
                if (string.Equals(sign, vSign, StringComparison.OrdinalIgnoreCase)) {
                    return ResultToJson.Json(true);
                }
                return ResultToJson.Json<bool>("sign不正确");
            }
            return ResultToJson.Json<bool>("header中partner无效");
        }

        /// <summary>
        /// 生成令牌
        /// </summary>
        /// <returns>The token.</returns>
        /// <param name="username">Username.</param>
        /// <param name="user_id">User identifier.</param>
        public token_info_dto GetToken(ITokenService tokenHelper, string username, long merchant_id,string merchant_no) {
            token_info_dto tokenInfo = new token_info_dto();
            var exp_dt = DateTime.Now.AddMinutes(timspanExpiredMinutes);
            int times = exp_dt.ToUnixInt();
            var payload = new Dictionary<string, object>(){
                    { "merchant_id", merchant_id.ToString() },
                    { "merchant_no", merchant_no.ToString() },
                    { "iss", username },
                    { "exp", times }
            };
            IJwtAlgorithm algorithm = new HMACSHA256Algorithm();
            IJsonSerializer serializer = new JsonNetSerializer();
            IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();
            JwtEncoder encoder = new JwtEncoder(algorithm, serializer, urlEncoder);
            string token = encoder.Encode(payload, token_key);
            tokenInfo.access_token = token;
            tokenInfo.expires_in = (timspanExpiredMinutes * 60);
            tokenInfo.expires_date = exp_dt;
            tokenInfo.id = merchant_id;
            tokenHelper.Save(tokenInfo);
            return tokenInfo;
        }
        /// <summary>
        /// 解码令牌
        /// </summary>
        /// <returns>The token.</returns>
        /// <param name="token">Token.</param>
        public string ValidateToken(string token) {
            try {
                IJsonSerializer serializer = new JsonNetSerializer();
                IDateTimeProvider provider = new UtcDateTimeProvider();
                IJwtValidator validator = new JwtValidator(serializer, provider);
                IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();
                IJwtDecoder decoder = new JwtDecoder(serializer, validator, urlEncoder);
                string decodedJwt = decoder.Decode(token, token_key, true);
                return decodedJwt;
            } catch {
                return "";
            }
        }

        /// <summary>  
        /// 获取合作号对应的合作Key,如果未能获取，则返回空字符串或者null  
        /// </summary>  
        /// <param name="partner"></param>  
        /// <returns></returns>  
        protected bool GetPartnerKey(string partner, out string partner_key) {
            partner_key = "";
            //var _iCompanyService = IocHelper.Current.Container.Resolve<ICompanyService>();
            //var company = _iCompanyService.Get(partner);
            //if (company != null) {
            //	partner_key = company.partner_key;
            //	return true;
            //}
            //return false;
            if (ConfigurationManager.AppSettings.AllKeys.Contains(partner)) {
                partner_key = ConfigurationManager.AppSettings[partner];
                return true;
            }
            return false;
        }
    }
}
